package com.ruoyi.system.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.dto.*;
import com.ruoyi.system.domain.vo.*;
import com.ruoyi.system.mapper.*;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.service.ITbDeviceAppsService;

import javax.annotation.Resource;

/**
 * 设备安装应用信息Service业务层处理
 *
 * @author ruoyi
 * @date 2025-07-23
 */
@Service
public class TbDeviceAppsServiceImpl implements ITbDeviceAppsService {
    @Autowired
    private TbDeviceAppsMapper tbDeviceAppsMapper;


    @Resource
    private TbDeviceMapper tbDeviceMapper;


    @Resource
    private TbAppVersionMapper tbAppVersionMapper;


    @Resource
    private TbTaskMapper tbTaskMapper;


    @Resource
    private TbTaskDetailMapper tbTaskDetailMapper;


    @Resource
    private TbDeviceInfoMapper tbDeviceInfoMapper;


    @Resource
    private TbTaskTargetMapper tbTaskTargetMapper;


    @Resource
    private TbTaskDetailLogsMapper tbTaskDetailLogsMapper;

    @Resource
    private TbAppCatalogMapper tbAppCatalogMapper;


    /**
     * 查询设备安装应用信息
     *
     * @param id 设备安装应用信息主键
     * @return 设备安装应用信息
     */
    @Override
    public TbDeviceApps selectTbDeviceAppsById(Long id) {
        return tbDeviceAppsMapper.selectTbDeviceAppsById(id);
    }

    /**
     * 查询设备安装应用信息列表
     *
     * @param tbDeviceApps 设备安装应用信息
     * @return 设备安装应用信息
     */
    @Override
    public List<TbDeviceApps> selectTbDeviceAppsList(TbDeviceApps tbDeviceApps) {
        return tbDeviceAppsMapper.selectTbDeviceAppsList(tbDeviceApps);
    }

    /**
     * 新增设备安装应用信息
     *
     * @param tbDeviceApps 设备安装应用信息
     * @return 结果
     */
    @Override
    public int insertTbDeviceApps(TbDeviceApps tbDeviceApps) {
        tbDeviceApps.setCreateTime(DateUtils.getNowDate());
        return tbDeviceAppsMapper.insertTbDeviceApps(tbDeviceApps);
    }

    /**
     * 修改设备安装应用信息
     *
     * @param tbDeviceApps 设备安装应用信息
     * @return 结果
     */
    @Override
    public int updateTbDeviceApps(TbDeviceApps tbDeviceApps) {
        tbDeviceApps.setUpdateTime(DateUtils.getNowDate());
        return tbDeviceAppsMapper.updateTbDeviceApps(tbDeviceApps);
    }

    /**
     * 批量删除设备安装应用信息
     *
     * @param ids 需要删除的设备安装应用信息主键
     * @return 结果
     */
    @Override
    public int deleteTbDeviceAppsByIds(Long[] ids) {
        return tbDeviceAppsMapper.deleteTbDeviceAppsByIds(ids);
    }

    /**
     * 删除设备安装应用信息信息
     *
     * @param id 设备安装应用信息主键
     * @return 结果
     */
    @Override
    public int deleteTbDeviceAppsById(Long id) {
        return tbDeviceAppsMapper.deleteTbDeviceAppsById(id);
    }

    @Override
    public List<TbDeviceInfoVO> listBypackageVersioncode(ItemDTO dto) {
        List<TbDeviceApps> deviceApps = tbDeviceAppsMapper.selectTbDeviceSnBy(dto.getPackageName(),
                dto.getPackageVersionnumber(), dto.getPackageVersioncode());

        if (CollectionUtils.isEmpty(deviceApps)) {
            return Collections.emptyList();
        }
        //获取设备号(去重)
        List<String> deviceSns = deviceApps.stream().distinct()
                .collect(Collectors.mapping(TbDeviceApps::getDeviceSn, Collectors.toList()));

        List<TbDeviceInfoVO> list = tbDeviceInfoMapper.selectBypackageVersioncode(deviceSns);
        return list;
    }

    @Override
    public List<TbTaskDetailVO> listTaskBypackageVersioncode(ItemDTO dto) {
        // 1. 根据版本号查询所有相关的任务明细
        //通过包名获取appname
        String appName = tbAppCatalogMapper.selectAppNameByPackageName(dto.getPackageName());
        if (StringUtils.isEmpty(appName)) {
            return Collections.emptyList();
        }
        List<TbTaskDetail> taskDetails = tbTaskDetailMapper.selectTbTaskDetailListByPackageVersioncode(appName,
                dto.getPackageVersionnumber(), dto.getPackageVersioncode());
        if (CollectionUtils.isEmpty(taskDetails)) {
            return Collections.emptyList();
        }

        // 2. 提取任务明细ID集合
        List<Long> taskDetailIds = taskDetails.stream()
                .map(TbTaskDetail::getId)
                .collect(Collectors.toList());

        // 3. 查询设备和飞机统计信息
        List<TaskDeviceStatDTO> deviceStats = tbTaskTargetMapper.selectDeviceStatByTaskDetailIds(taskDetailIds);
        Map<Long, TaskDeviceStatDTO> deviceStatMap = deviceStats.stream()
                .collect(Collectors.toMap(TaskDeviceStatDTO::getTaskDetailId, Function.identity()));

        List<TaskPlaneStatDTO> planeStats = tbTaskTargetMapper.selectPlaneStatByTaskDetailIds(taskDetailIds);
        Map<Long, TaskPlaneStatDTO> planeStatMap = planeStats.stream()
                .collect(Collectors.toMap(TaskPlaneStatDTO::getTaskDetailId, Function.identity()));

        // 4. 查询主任务信息（仅用于获取任务名称）
        List<Long> taskIds = taskDetails.stream()
                .map(TbTaskDetail::getTaskId)
                .distinct()
                .collect(Collectors.toList());
        List<TbTask> tasks = tbTaskMapper.selectTaskListByIds(taskIds);
        Map<Long, TbTask> taskMap = tasks.stream()
                .collect(Collectors.toMap(TbTask::getId, Function.identity()));

        // 5. 构建分任务VO列表
        List<TbTaskDetailVO> result = new ArrayList<>();

        for (TbTaskDetail detail : taskDetails) {
            TaskDeviceStatDTO deviceStat = deviceStatMap.get(detail.getId());
            TaskPlaneStatDTO planeStat = planeStatMap.get(detail.getId());
            TbTask task = taskMap.get(detail.getTaskId());

            int totalDevices = deviceStat != null ? deviceStat.getTotalCount() : 0;
            int successDevices = deviceStat != null ? deviceStat.getSuccessCount() : 0;
            int planeCount = planeStat != null ? planeStat.getPlaneCount() : 0;

            // 构建分任务VO
            TbTaskDetailVO subVO = new TbTaskDetailVO();
            subVO.setId(detail.getId());
            subVO.setTaskName(task != null ? task.getTaskName() : "未知任务");
            if (detail.getPushPackageType() == 1) {

                subVO.setAppOrPackageName(detail.getAppName());
            }
            if (detail.getPushPackageType() == 2) {
                subVO.setAppOrPackageName(detail.getPackageName());
            }
            subVO.setPackageVersionnumber(detail.getPackageVersionnumber());

            int deviceCount = tbTaskTargetMapper.getDeviceCountByDetailId(detail.getId());
            int totalDeviceCount = tbDeviceMapper.selectDeviceCountOnline();
            // 决定任务目标显示内容
            String taskTarget;
            if (deviceCount == totalDeviceCount) {
                taskTarget = String.format("所有飞机(%d台设备)", totalDevices);
            } else {
                taskTarget = String.format("%d架飞机(%d台设备)", planeCount, totalDevices);
            }
            subVO.setTaskTarget(taskTarget);

            subVO.setProgressDetail(String.format("%d/%d", successDevices, totalDevices));
            subVO.setStatus(task.getTaskStatus());
            subVO.setProgress(totalDevices > 0 ?
                    Math.round(((double) successDevices / totalDevices) * 100 * 10) / 10.0 :
                    0.0);
            subVO.setStartTime(detail.getStartTime());
            subVO.setEndTime(detail.getEndTime());

            result.add(subVO);
        }

        return result;
    }

    @Override
    public int updateAppStatus(Long id) {
        return tbAppCatalogMapper.updateAppNameStatus(id);
    }

    @Override
    public AviationAppStatsVO getdecommissionedInfo(Long catalogId) {
        AviationAppStatsVO statsVO = new AviationAppStatsVO();

        // 查询应用名称
        String appName = tbAppCatalogMapper.selectAppNameById(catalogId);
        if (StringUtils.isEmpty(appName)) {
            return statsVO;
        }

        // 1. 查询安装了该应用的所有设备应用记录
        List<TbDeviceApps> deviceAppInfos = tbDeviceAppsMapper.selectDeviceAppInfoByApp(appName);
        if (CollectionUtils.isEmpty(deviceAppInfos)) {
            return statsVO;
        }

        // 提取去重的设备SN列表
        Set<String> deviceSns = deviceAppInfos.stream()
                .map(TbDeviceApps::getDeviceSn)
                .collect(Collectors.toSet());

        // 2. 查询设备信息
        List<TbDevice> devices = tbDeviceMapper.selectByDeviceSns(new ArrayList<>(deviceSns));
        if (CollectionUtils.isEmpty(devices)) {
            return statsVO;
        }

        // 获取设备id集合
        List<Long> deviceIds = devices.stream()
                .map(TbDevice::getId)
                .collect(Collectors.toList());
        statsVO.setDeviceIds(deviceIds);


        // 3. 统计飞机数(去重)
        Set<String> airplaneCodes = devices.stream()
                .map(TbDevice::getAirplaneCode)
                .filter(Objects::nonNull)
                .filter(code -> !code.trim().isEmpty())
                .collect(Collectors.toSet());
        statsVO.setInstalledAircraftCount(airplaneCodes.size());

        // 4. 统计设备总数
        statsVO.setTotalDevicesCount(devices.size());

        // 5. 查询设备连接状态，统计在线设备数
        List<TbDeviceInfo> deviceInfos = tbDeviceInfoMapper.selectByDeviceSns(new ArrayList<>(deviceSns));
        long onlineCount = deviceInfos.stream()
                .filter(info -> info.getConnectionStatus() != null && info.getConnectionStatus() == 1)
                .count();
        statsVO.setOnlineDevicesCount((int) onlineCount);

        // 6. 精确计算预计流量
        //  BigDecimal totalTraffic = calculateEstimatedTraffic(appName, deviceAppInfos);
        //  statsVO.setEstimatedTraffic(totalTraffic);

        return statsVO;
    }

    @Override
    public List<AirPlaneAndDeviceInfoVO> selectDeviceAppInfoByApp(Long catalogId) {
        // 查询应用名称
        String appName = tbAppCatalogMapper.selectAppNameById(catalogId);
        if (StringUtils.isEmpty(appName)) {
            return Collections.emptyList();
        }

        // 1. 查询安装了该应用的所有设备应用记录
        List<TbDeviceApps> deviceAppInfos = tbDeviceAppsMapper.selectDeviceAppInfoByApp(appName);
        if (CollectionUtils.isEmpty(deviceAppInfos)) {
            return Collections.emptyList();
        }

        // 提取去重的设备SN列表
        Set<String> deviceSns = deviceAppInfos.stream()
                .map(TbDeviceApps::getDeviceSn)
                .collect(Collectors.toSet());

        // 2. 查询设备信息
        List<TbDevice> devices = tbDeviceMapper.selectByDeviceSns(new ArrayList<>(deviceSns));
        if (CollectionUtils.isEmpty(devices)) {
            return Collections.emptyList();
        }

        // 3. 过滤有飞机号的设备并按飞机号分组
        Map<String, List<TbDevice>> planeDeviceMap = devices.stream()
                .filter(device -> StringUtils.isNotBlank(device.getAirplaneCode()))
                .collect(Collectors.groupingBy(TbDevice::getAirplaneCode));

        // 4. 转换为VO列表
        return planeDeviceMap.entrySet().stream()
                .map(entry -> {
                    List<TbDevice> planeDevices = entry.getValue();
                    List<Long> deviceIds = planeDevices.stream()
                            .map(TbDevice::getId)
                            .collect(Collectors.toList());

                    AirPlaneAndDeviceInfoVO vo = new AirPlaneAndDeviceInfoVO();
                    vo.setPlaneCode(entry.getKey());
                    vo.setDeviceNum(planeDevices.size());
                    vo.setDeviceIds(deviceIds);
                    return vo;
                })
                .collect(Collectors.toList());
    }


    @Override
    public int updateAppNameStatusByPlaneCodes(DecommissionedByPlaneCodeRequest request) {
        //通过飞机号查询到 设备信息
        List<TbDevice> devices = tbDeviceMapper.selectListByPlaneCodes(request.getPlaneCodes());
        //获取到 deviceSn
        List<String> deviceSns = devices.stream()
                .map(TbDevice::getDevSn)
                .collect(Collectors.toList());
        // 批量更新设备应用状态
        return tbDeviceAppsMapper.updateAppNameStatusByPlaneCodes(deviceSns, request.getCatalogId());
    }

    @Override
    public List<AirPlaneAndDeviceDetailInfoVO> getDeviceAppAirplaneAndDeviceInfoByAppName(Long catalogId, String deviceSn, String planeCode) {
        // 查询应用名称
        String appName = tbAppCatalogMapper.selectAppNameById(catalogId);
        if (StringUtils.isEmpty(appName)) {
            return Collections.emptyList();
        }

        // 1. 查询安装了该应用的所有设备应用记录(未被禁用)
        List<TbDeviceApps> deviceAppInfos = tbDeviceAppsMapper.selectDeviceAppInfoByApp(appName);
        if (CollectionUtils.isEmpty(deviceAppInfos)) {
            return Collections.emptyList();
        }

        // 提取去重的设备SN列表
        Set<String> deviceSns = deviceAppInfos.stream()
                .map(TbDeviceApps::getDeviceSn)
                .collect(Collectors.toSet());

        // 2. 查询设备详细信息，应用过滤条件
        List<TbDevice> devices = tbDeviceMapper.selectByDeviceSnsWithFilter(new ArrayList<>(deviceSns), planeCode);
        if (CollectionUtils.isEmpty(devices)) {
            return Collections.emptyList();
        }

        // 3. 按飞机编号分组设备
        Map<String, List<TbDevice>> airplaneDeviceMap = devices.stream()
                .collect(Collectors.groupingBy(TbDevice::getAirplaneCode));

        List<AirPlaneAndDeviceDetailInfoVO> infoVOS = new ArrayList<>();

        for (Map.Entry<String, List<TbDevice>> entry : airplaneDeviceMap.entrySet()) {
            String airplaneCode = entry.getKey();
            List<TbDevice> deviceList = entry.getValue();

            // 获取当前飞机下的设备ID列表
            List<Long> currentAirplaneDeviceIds = deviceList.stream()
                    .map(TbDevice::getId)
                    .collect(Collectors.toList());

            // 获取当前飞机下的设备SN列表
            List<String> deviceSnList = deviceList.stream()
                    .map(TbDevice::getDevSn)
                    .collect(Collectors.toList());

            // 查询设备详情（带过滤条件）
            List<TbDeviceVO> deviceVOs = tbDeviceMapper.selectByDeviceSnList(deviceSnList, deviceSn);

            AirPlaneAndDeviceDetailInfoVO infoVO = new AirPlaneAndDeviceDetailInfoVO();
            infoVO.setAirplaneCode(airplaneCode);
            infoVO.setDeviceCount(deviceList.size());
            infoVO.setVos(deviceVOs);
            infoVO.setDeviceIds(currentAirplaneDeviceIds);

            infoVOS.add(infoVO);
        }

        return infoVOS;
    }

    private AirPlaneAndDeviceDetailInfoAndDeviceIdsVO createEmptyDetailResult() {
        AirPlaneAndDeviceDetailInfoAndDeviceIdsVO result = new AirPlaneAndDeviceDetailInfoAndDeviceIdsVO();
        result.setInfoVOS(Collections.emptyList());
        result.setTotalDeviceIds(Collections.emptyList());
        return result;
    }

    @Override
    public int updateAppNameStatusByDeviceSn(DecommissionedByPlaneCodeandDeviceInfoRequest request) {
        return tbDeviceAppsMapper.updateAppNameStatusByDeviceSn(request.getDeviceSn(), request.getAppName());
    }

    /**
     * 计算预估流量（GB）
     *
     * @param appName        应用名称（用于查询校验）
     * @param deviceAppInfos 设备应用信息列表
     * @return 预估流量（GB，保留2位小数）
     */
    private BigDecimal calculateEstimatedTraffic(String appName, List<TbDeviceApps> deviceAppInfos) {
        // 1. 提取所有版本号（去重）
        Set<String> versionCodes = deviceAppInfos.stream()
                .map(TbDeviceApps::getPackageVersioncode)
                .collect(Collectors.toSet());

        // 2. 批量查询版本对应的包大小（MB）
        List<TbAppVersion> appVersions = tbAppVersionMapper.selectByPackageNameAndVersionCodes(

                new ArrayList<>(versionCodes));

        // 3. 构建版本号到包大小（MB）的映射
        Map<String, Double> versionSizeMap = appVersions.stream()
                .collect(Collectors.toMap(
                        TbAppVersion::getPackageVersioncode,
                        TbAppVersion::getPackageSize));

        // 4. 计算总兆字节数（MB）
        double totalMB = 0.0;
        for (TbDeviceApps appInfo : deviceAppInfos) {
            Double sizeMB = versionSizeMap.get(appInfo.getPackageVersioncode());
            if (sizeMB != null) {
                totalMB += sizeMB;
            }
        }

        // 5. 转换为GB (1GB = 1024 MB)，保留2位小数
        return BigDecimal.valueOf(totalMB)
                .divide(BigDecimal.valueOf(1024), 2, RoundingMode.HALF_UP);
    }

}
